<!DOCTYPE html>
<script src="../../resources/gesture-util.js"></script>
<script src="../../resources/testharness.js"></script>
<script src="../../resources/testharnessreport.js"></script>
<style>
#scroller {
  overflow: scroll;
  height: 300px;
  width: 300px;
  margin: 0;
  padding: 0;
  scroll-snap-type: y mandatory;
}

#container {
  margin: 0;
  padding: 0;
  width: 600px;
  height: 2000px;
}

#initial-area {
  position: relative;
  top: 0;
  width: 200px;
  height: 200px;
  background-color: red;
  scroll-snap-align: start;
}

#target-area {
  position: relative;
  top: 200px;
  width: 200px;
  height: 200px;
  background-color: green;
  scroll-snap-align: start;
}
</style>

<div id="scroller">
  <div id="container">
    <div id="initial-area"></div>
    <div id="target-area"></div>
  </div>
</div>

<script>
const scroller = document.getElementById('scroller');
const target_area = document.getElementById('target-area');
const macPlatform = navigator.platform.indexOf('Mac') == 0;

function cleanup() {
  scroller.scrollTo(0,0);
  assert_equals(scroller.scrollTop, 0);

  target_area.style.setProperty('top', '200px');
  assert_equals(scroller.scrollTop, 0);
}

function scrollTop() {
  return scroller.scrollTop;
}

function wheelScroll(delta, x, y, direction) {
  // A mouse wheel scroll comes from mouse input with imprecise delta.
  return smoothScroll(delta, x ,y , GestureSourceType.MOUSE_INPUT, direction,
                      SPEED_INSTANT, false /* is precise delta */);
}

function keyPress(key) {
  return new Promise((resolve, reject) => {
    if (window.eventSender) {
      eventSender.keyDown(key);
      resolve();
    }
    else {
      reject('This test requires window.eventSender');
    }
  })
}

function touchScroll(delta, x, y, direction) {
  return smoothScroll(delta, x, y, GestureSourceType.TOUCH_INPUT, direction,
                      SPEED_INSTANT);
}

promise_test (async t => {
  t.add_cleanup(cleanup);

  await mouseClickOn(10, 10);
  const scrollPromise = waitForScrollEvent(scroller);
  await wheelScroll(250 /* pixels to scroll */, 50, 50, 'down');
  await scrollPromise;
  // Use time based wait since overshooting the snap target position.
  await waitForAnimationEndTimeBased(scrollTop);
  assert_equals(scrollTop(), 400);

  target_area.style.setProperty('top', '600px');
  assert_equals(scroller.scrollTop, 800);
}, "Layout changes should make the scroller resnap to targets set from wheel"
   + " scrolling");

promise_test (async t => {
  t.add_cleanup(cleanup);

  await mouseClickOn(10, 10);
  await keyPress('ArrowDown');
  await waitForScrollEnd(scroller, scrollTop, 400);

  target_area.style.setProperty('top', '600px');
  assert_equals(scroller.scrollTop, 800);
}, "Layout changes should make the scroller resnap to targets set from keyboard"
   + " scrolling");

if (!macPlatform) {
  // MacOS devices do not have touch screens Test is not relevant.
  promise_test (async t => {
    t.add_cleanup(cleanup);

    await mouseClickOn(10, 10);
    const scrollPromise = waitForScrollEvent(scroller);
    await touchScroll(250 /* delta */, 50, 50, 'down');
    await scrollPromise;
    // Use time based wait since overshooting the scroll snap position.
    await waitForAnimationEndTimeBased(scrollTop);
    assert_equals(scroller.scrollTop, 400);

    target_area.style.setProperty('top', '600px');
    assert_equals(scroller.scrollTop, 800);
  }, "Layout changes should make the scroller resnap to targets set from gesture"
     + " scrolling");
}

</script>
